import { NextFunction, Request } from "express";
import { Method } from "axios";
import { Response, Service } from "../response";
import jwt from "jsonwebtoken";
import { AdminUserModel } from "@/models/admin/User";
import { AdminUser } from "@/types/admin/auth";
import { RoleModel } from "@/models/admin/Role";
import { Permission } from "@/types/admin/permission";
import { Types } from "mongoose";
import { PermissionModel } from "@/models/admin/Permission";

// 路由白名单（不需要携带登录凭证的请求）
const whiteList: { path: string; method: Method }[] = [
    {
        path: "/auth/captcha",
        method: "GET",
    },
    {
        path: "/auth/login",
        method: "POST",
    },
    {
        path: "/auth/logout",
        method: "POST",
    },
];

export const setUserRolePermission = async (req: Request, res: Response, forceUpdate?: boolean) => {
    if (forceUpdate || !req.session.user) req.session.user = (await AdminUserModel.findOne({ _id: req.session.userId })) as AdminUser;
    if (!req.session.user) return res.sendResponse!(401, null, "请先登录");
    if (!req.session.user.status) return res.sendResponse!(401, null, "账号已禁用，请联系管理员");
    if (forceUpdate || !req.session.roles) {
        const roles = await RoleModel.aggregate([
            {
                $match: { _id: { $in: req.session.user.roles } },
            },
            {
                $lookup: {
                    localField: "permissions",
                    foreignField: "_id",
                    as: "permissions",
                    from: "permissions",
                },
            },
        ]);
        req.session.roles = roles;
    }
    if (forceUpdate || !req.session.permissions) {
        let permissions = [];
        const isAdmin = req.session.roles?.some(item => item.key === "admin");
        if (isAdmin) {
            permissions = await PermissionModel.find();
        } else {
            permissions = (req.session.roles?.map(item => item.permissions).flat() as unknown as Permission[]) || [];
        }
        req.session.permissions = permissions;
    }
};
// 管理端身份认证中间件
export const adminAuthMiddleware = async (req: Request, res: Response, next: NextFunction) => {
    let { path, method } = req as Request & { method: Method };
    const whiteListResult = whiteList.find(item => item.path === path && item.method === method);
    if (whiteListResult) return next();
    const token = req.headers.authorization?.split(`Bearer `)[1];
    if (!token) return res.sendResponse!(401, null, "请先登录");
    try {
        const tokenRes = jwt.verify(token, process.env.ADMINJWTSECRET!);
        if (!tokenRes) return res.sendResponse!(401, null, "请先登录");
        const { _id } = tokenRes as { _id: string };
        req.session.userId = _id;
        await setUserRolePermission(req, res);
        const pathArr = path.split("/");
        if (Types.ObjectId.isValid(pathArr[pathArr.length - 1])) {
            pathArr[pathArr.length - 1] = ":_id";
            path = pathArr.join("/");
        }
        const hasCurrentPermission = req.session.permissions?.some(item => item.path === path && item.method === method);
        const isAdmin = req.session.roles?.some(item => item.key === "admin");
        if (!hasCurrentPermission && !isAdmin) return res.sendResponse!(403, null, "暂无权限");
        next();
    } catch {
        return res.sendResponse!(401, null, "登录过期");
    }
};
